package com.taldh.netty.io.socket.discard;

import com.taldh.netty.common.util.Logger;
import com.taldh.netty.io.NioDemoConfig;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

public class NioDiscardServer {

    static void startServer () throws IOException {
        // 1. 获取selector实例
        Selector selector = Selector.open();

        // 2. 获取通道
        ServerSocketChannel serverSocketChannel  = ServerSocketChannel.open();

        // 3. 设置为非阻塞
        serverSocketChannel.configureBlocking(false);

        // 4. 绑定连接
        serverSocketChannel.bind(
                new InetSocketAddress(NioDemoConfig.SOCKET_SERVER_IP, NioDemoConfig.SOCKET_SERVER_PORT)
        );
        Logger.info("服务器启动成功");

        // 5. 讲通道注册到选择器上，并制定监听事件
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        // 6. 轮询感兴趣的IO就绪事件 （选择器集合）
        while (selector.select() > 0) {
            // 7. 获取选择键集合
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                // 8. 获取单个选择键，并处理
                SelectionKey selectionKey = iterator.next();

                // 9. 判断key是具体什么事件
                if (selectionKey.isAcceptable()) {
                    // 10. 若选择键的IO事件是 “连接选择就绪”事件，就获取客户端连接
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    // 11. 切换为非阻塞模式
                    socketChannel.configureBlocking(false);
                    // 12. 讲连接通道的可读事件注册到选择器上
                    socketChannel.register(selector, SelectionKey.OP_READ);
                } else if (selectionKey.isReadable()) {
                    // 13. 若选择键的IO事件是“可读”事件，读取数据
                    SocketChannel channel = (SocketChannel)selectionKey.channel();
                    // 14. 读取数据，然后丢弃
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    int length = 0;
                    while ((length = channel.read(buffer)) > 0) {
                        buffer.flip();
                        Logger.info(new String(buffer.array(), 0, length));
                        buffer.clear();
                    }
                }

                // 15. 移除选择键
                iterator.remove();
            }
        }

        // 16. 关闭连接
        serverSocketChannel.close();
    }

    public static void main(String[] args) throws IOException {
        startServer();
    }

}
